package functionroots.methods;

import functionroots.primitives.DerivableRealFunction;
import functionroots.primitives.RealFunction;

/**
 * Implementa o método de Newton-Raphson para a obtenção de zeros de funções de
 * uma variável real.
 * @author orion
 */
public class NewtonRaphson extends FixedPoint {

    private class IterationFunction implements RealFunction {

        private DerivableRealFunction baseFunction;

        public IterationFunction(RealFunction function) {
            if (function instanceof DerivableRealFunction) {
                baseFunction = (DerivableRealFunction) function;
            } else {
                throw new IllegalArgumentException("Newton-Raphson's target " +
                        "function must be derivable!");
            }
        }

        public double value(double x) {
            return x - baseFunction.value(x) / baseFunction.derivative(x);
        }

        public String text(double x) {
            throw new UnsupportedOperationException("Not supported yet.");
        }
    }

    /**
     * Instancia o método de Newton-Raphson com uma função, precisão e número
     * máximo de iterações pré-definidos.
     * @param function a função alvo.
     * @param precision a precisão pretendida.
     * @param maxIterations o número máximo de iterações.
     */
    public NewtonRaphson(RealFunction function, double precision, long maxIterations) {
        super(function, null, precision, maxIterations);
        setIterationFunction(new IterationFunction(function));
    }

    /**
     * Instancia o método de Newton-Raphson com uma função e precisão
     * pré-definidas.
     * @param function a função alvo.
     * @param precision a precisão pretendida.
     */
    public NewtonRaphson(RealFunction function, double precision) {
        super(function, null, precision);
        setIterationFunction(new IterationFunction(function));
    }
}
